package rpc.aop;

import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.beans.factory.config.BeanDefinitionHolder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ClassPathBeanDefinitionScanner;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import rpc.annotation.TargetServiceName;

import java.util.Set;

public class XiaobaibaiClientInterfacesScanner extends ClassPathBeanDefinitionScanner {

    /**
     * ClassPathBeanDefinitionScanner接口的作用
     * 就是将指定包下的类通过一定规则过滤后 将Class 信息包装成 BeanDefinition 的形式注册到IOC容器中。
     */
    public XiaobaibaiClientInterfacesScanner(BeanDefinitionRegistry registry) {
        super(registry, false);//不使用默认filter

    }


    @Override
    protected Set<BeanDefinitionHolder> doScan(String... basePackages) {
        //添加扫描类过滤器
        this.addFilter();
        //在目标包下,扫描并录入Bean定义信息
        Set<BeanDefinitionHolder> beanDefinitionHolders = super.doScan(basePackages);
        if (beanDefinitionHolders.isEmpty()) {
            throw new NullPointerException("No interfaces");
        }
        //接口扫描完毕去修改接口bean信息
        this.updateBeanDefinition(beanDefinitionHolders);
        //返回注册进入IOC容器
        return beanDefinitionHolders;
    }

    /**
     * 只扫描接口
     * @param beanDefinition bean定义
     * @return boolean
     */
    @Override
    protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
        //入参过滤器通过的类
        AnnotationMetadata metadata = beanDefinition.getMetadata();
        return metadata.isInterface();
    }

    /**
     * 扫描哪些类?
     */
    private void addFilter() {
        addIncludeFilter(new AnnotationTypeFilter(TargetServiceName.class));//通过过滤器
//        addExcludeFilter();//添加排除过滤器
    }

    /**
     * 为扫描到的接口创建代理对象
     *
     * @param beanDefinitionHolders beanDefinitionHolders
     */

    private void updateBeanDefinition(Set<BeanDefinitionHolder> beanDefinitionHolders) {
        for (BeanDefinitionHolder beanDefinitionHolder : beanDefinitionHolders) {
            //转换成高级beanDefinition
            GenericBeanDefinition beanDefinition = ((GenericBeanDefinition) beanDefinitionHolder.getBeanDefinition());
            //添加构造函数
            beanDefinition.getConstructorArgumentValues().addGenericArgumentValue(beanDefinition.getBeanClassName());
            //改变bean的真实类型为bean工厂,bean工厂会返回它所创建的bean
            beanDefinition.setBeanClass(XiaobaibaiClientProxyFactoryBean.class);
            //修改注入方式
            beanDefinition.setAutowireMode(GenericBeanDefinition.AUTOWIRE_BY_TYPE);
        }
    }

}